# coding:utf-8
"""
Author: 11203
Date:  16:00
Name: token_utils
"""
import datetime
from datetime import timedelta

import jwt
from flask import current_app
# 如果你在 itsdangerous 中既找不到 TimedJSONWebSignatureSerializer
# 也找不到 JSONWebSignatureSerializer，很可能是因为你使用的是 itsdangerous 2.1.0 及以上版本
# ，这个版本对 API 进行了进一步调整，采用了全新的命名方式。
from itsdangerous import TimedSerializer, SignatureExpired, BadSignature
from jwt import PyJWTError

from common.utils import contants
from common.utils.contants import JWT_ALGORITHM


def create_token_by_default(uid):
    """
    使用python自带的工具包生成token
    :param uid: 用户id
    :return:
    """
    # 创建带过期时间的序列化器（替代 TimedJSONWebSignatureSerializer）
    serializer = TimedSerializer(secret_key=contants.JWT_SECRET_KEY, algorithm=contants.JWT_ALGORITHM)
    # 生成带过期时间的签名数据（expires_in 单位为秒）
    token = serializer.dumps(uid, expires_in= contants.JWT_EXPIRES_SECOND)
    return token


def verify_tokens_by_default(token):
    """
    使用python自带的工具包生成的token的验证
    :param token: token
    :return:
    """
    try:
        serializer = TimedSerializer(secret_key=contants.JWT_SECRET_KEY, algorithm=contants.JWT_ALGORITHM)
        result = serializer.loads(token)
        return result
    except SignatureExpired:
        current_app.logger.error('签名已过期：The signature has expired')
        raise Exception('签名已过期')
    except BadSignature:
        current_app.logger.error('签名无效：The signature is invalid')
        raise Exception('签名无效')

# 使用pyjwt生成token
def create_token_by_pyjwt(uid):
    # 参数1：payload是一个字典包括需要加密的信息和有效时间
    # 参数2：密钥
    # 参数3：算法名称
    payload = dict()
    payload['id'] = uid
    # token过期时间，必须是标准时间（时间戳）
    # python 3.11中，datetime.datetime.now(datetime.UTC) 代替了原来的：datetime.datetime。utcnow()
    payload['exp'] = datetime.datetime.now(datetime.UTC) + timedelta(seconds=contants.JWT_EXPIRES_SECOND)
    token = jwt.encode(payload=payload, key=contants.JWT_SECRET_KEY, algorithm=JWT_ALGORITHM)
    return token

# 使用pyjwt进行token验证
def verify_tokens_by_pyjwt(token):
    try:
        result = jwt.decode(token, contants.JWT_SECRET_KEY, algorithms=JWT_ALGORITHM)
        return result
    except PyJWTError as e:
        current_app.logger.error(e)
        return {'message': 'token验证失败'}
